﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;

namespace Convert_DVR_MS_to_iTunes
{
    public class FileHelper
    {
        // http://msdn.microsoft.com/en-us/library/bb513869.aspx

        private List<string> m_FoundFiles;
        private StatusStrip m_Status = null;
        private ToolStripStatusLabel m_Searching = null;

        public List<string> FileFind(string drive, string filePattern, bool useStackMethod, StatusStrip status, ToolStripStatusLabel searching)
        {
            m_FoundFiles = new List<string>();
            m_Status = status;
            m_Searching = searching;

            DirectoryInfo rootDir = new DirectoryInfo(drive);

            if (useStackMethod)
                TraverseTree(rootDir, filePattern);
            else
                WalkDirectoryTree(rootDir, filePattern);

            return m_FoundFiles;
        }

        public List<string> FileFind(string filePattern, bool useStackMethod, StatusStrip status, ToolStripStatusLabel searching)
        {
            m_FoundFiles = new List<string>();
            m_Status = status;
            m_Searching = searching;

            // Start with drives if you have to search the entire computer.
            string[] drives = System.Environment.GetLogicalDrives();

            foreach (string dr in drives)
            {
                DriveInfo di = new DriveInfo(dr);

                // Here we skip the drive if it is not ready to be read. This
                // is not necessarily the appropriate action in all scenarios.
                if (di.IsReady && di.DriveType == DriveType.Fixed)
                {
                    DirectoryInfo rootDir = di.RootDirectory;

                    if (useStackMethod)
                        TraverseTree(rootDir, filePattern);
                    else
                        WalkDirectoryTree(rootDir, filePattern);
                }
            }

            return m_FoundFiles;
        }

        private void WalkDirectoryTree(DirectoryInfo root, string filePattern)
        {
            FileInfo[] files = null;
            DirectoryInfo[] subDirs = null;

            // First, process all the files directly under this folder
            try
            {
                files = root.GetFiles(filePattern);
            }
            catch { }

            if (files != null)
            {
                foreach (FileInfo file in files)
                {
                    m_FoundFiles.Add(file.FullName);
                }
            }

            // Now find all the subdirectories under this directory.
            try
            {
                subDirs = root.GetDirectories();
            }
            catch { }

            foreach (DirectoryInfo dirInfo in subDirs)
            {
                // Resursive call for each subdirectory.
                WalkDirectoryTree(dirInfo, filePattern);
            }
        }

        private void TraverseTree(DirectoryInfo root, string filePattern)
        {
            // Data structure to hold names of subfolders to be examined for files.
            Stack<string> dirs = new Stack<string>(20);

            dirs.Push(root.ToString());

            while (dirs.Count > 0)
            {
                string currentDir = dirs.Pop();
                string[] subDirs = null;

                // First, process all the files directly under this folder
                string[] files = null;
                try
                {
                    files = Directory.GetFiles(currentDir, filePattern);
                }
                catch (DirectoryNotFoundException ex)
                {
                    continue;
                }
                catch (UnauthorizedAccessException ex)
                {
                    continue;
                }

                if (m_Searching != null)
                {
                    m_Searching.Text = currentDir;
                    m_Status.Refresh();
                    Application.DoEvents();
                }
                // Perform the required action on each file here.
                foreach (string file in files)
                {
                    m_FoundFiles.Add(file);
                }

                // Now find all the subdirectories under this directory.
                try
                {
                    subDirs = Directory.GetDirectories(currentDir);
                }
                catch { }

                // Push the subdirectories onto the stack for traversal.
                if (subDirs != null)
                {
                    foreach (string str in subDirs)
                        dirs.Push(str);
                }
            }
        }
    }
}
